/* Copyright (c) 2022-2025 Qualcomm Technologies International, Ltd. */
/* %%version */

#include "csr_synergy.h"

#ifndef EXCLUDE_GATT_XPAN_CLIENT_MODULE

#include "gatt_xpan_client.h"
#include "gatt_xpan_client_private.h"
#include "gatt_xpan_client_notification.h"
#include "gatt_xpan_client_common.h"
#include "gatt_xpan_client_debug.h"

extern gatt_xpan_client *xpanClientMain;

void GattXpanClientRegisterForNotificationReq(ServiceHandle serviceHandle, XpanClientCharacteristicId charId, bool notificationsEnable)
{
    GXPANC *gattXpanClient = ServiceHandleGetInstanceData(serviceHandle);
    uint16 handle = 0;

    if (gattXpanClient)
    {
        if (xpanClientGetHandle(gattXpanClient, charId, &handle, XPAN_CLIENT_CHAR_TYPE_CHARACTERISTIC_CLIENT_CONFIG))
        {
            MAKE_XPAN_CLIENT_MESSAGE(XpanClientInternalMsgSetNotification);

            message->notificationsEnable = notificationsEnable;
            message->srvcHndl = gattXpanClient->srvcElem->service_handle;
            message->handle = handle;

            GATT_XPAN_CLIENT_INFO("GXPANC: handle 0x%x enable %x\n", handle, notificationsEnable);

            XpanClientMessageSend(xpanClientMain->lib_task,
                                 XPAN_CLIENT_INTERNAL_MSG_NOTIFICATION_REQ,
                                 message);
        }
    }
    else
    {
        GATT_XPAN_CLIENT_PANIC("Invalid XPAN Client instance!\n");
    }
}

/***************************************************************************
 * Handler for: XPAN_CLIENT_INTERNAL_MSG_NOTIFICATION_REQ
 ***************************************************************************/
void xpanClientHandleInternalRegisterForNotification(GXPANC *const xpanClient,
                                                     bool enable,
                                                     uint16 handle)
{
    uint8* value = (uint8*)(CsrPmemZalloc(XPAN_CLIENT_CHARACTERISTIC_CONFIG_SIZE));

    value[0] = (enable)? XPAN_NOTIFICATION_VALUE : 0;
    value[1] = 0;

    CsrBtGattWriteReqSend(xpanClient->srvcElem->gattId,
                          xpanClient->srvcElem->cid,
                          handle,
                          0,
                          XPAN_CLIENT_CHARACTERISTIC_CONFIG_SIZE,
                          value);
}

/****************************************************************************/
static void makeXpanClientStoredSsidIndMsg(GXPANC *xpanClient, uint16 size, CsrUint8* indData)
{
    MAKE_XPAN_CLIENT_MESSAGE(GattXpanClientStoredSsidInd);

    GATT_XPAN_CLIENT_INFO("GXPANC: StoredSsid ind. handle = 0x%x size = 0x%x\n", xpanClient->srvcElem->service_handle, size);

    message->clntHndl = xpanClient->srvcElem->service_handle;

    xpanClientDecodeStoredSsid(&message->storedSsid, size, indData);

    XpanClientMessageSend(xpanClient->app_task, GATT_XPAN_CLIENT_STORED_SSID_IND, message);
}

/****************************************************************************/
static void makeXpanClientIpv4AddressIndMsg(GXPANC *xpanClient, uint16 size, CsrUint8* indData)
{
    MAKE_XPAN_CLIENT_MESSAGE(GattXpanClientIpv4AddressInd);

    GATT_XPAN_CLIENT_INFO("GXPANC: Ipv4Address ind. handle = 0x%x size = 0x%x\n", xpanClient->srvcElem->service_handle, size);

    message->clntHndl = xpanClient->srvcElem->service_handle;

    xpanClientDecodeIpAddressData(&message->ipAddressData, size, indData, XPAN_CLIENT_IPV4_ADDRESS_LENGTH_OCTETS);

    XpanClientMessageSend(xpanClient->app_task, GATT_XPAN_CLIENT_IPV4_ADDRESS_IND, message);
}

/****************************************************************************/
static void makeXpanClientIpv6AddressIndMsg(GXPANC *xpanClient, uint16 size, CsrUint8* indData)
{
    MAKE_XPAN_CLIENT_MESSAGE(GattXpanClientIpv6AddressInd);

    GATT_XPAN_CLIENT_INFO("GXPANC: Ipv6Address ind. handle = 0x%x size = 0x%x\n", xpanClient->srvcElem->service_handle, size);

    message->clntHndl = xpanClient->srvcElem->service_handle;

    xpanClientDecodeIpAddressData(&message->ipAddressData, size, indData, XPAN_CLIENT_IPV6_ADDRESS_LENGTH_OCTETS);

    XpanClientMessageSend(xpanClient->app_task, GATT_XPAN_CLIENT_IPV6_ADDRESS_IND, message);
}

/****************************************************************************/
static void makeXpanClientL2capTcpPortIndMsg(GXPANC *xpanClient, uint16 size, CsrUint8* indData)
{
    MAKE_XPAN_CLIENT_MESSAGE(GattXpanClientL2capTcpPortInd);

    GATT_XPAN_CLIENT_INFO("GXPANC: L2capTcpPort ind. handle = 0x%x size = 0x%x\n", xpanClient->srvcElem->service_handle, size);

    message->clntHndl = xpanClient->srvcElem->service_handle;

    xpanClientDecodeL2capTcpPort(&message->l2capTcpPort, size, indData);

    XpanClientMessageSend(xpanClient->app_task, GATT_XPAN_CLIENT_L2CAP_TCP_PORT_IND, message);
}

/****************************************************************************/
static void makeXpanClientUdpPortIndMsg(GXPANC *xpanClient, uint16 size, CsrUint8* indData)
{
    MAKE_XPAN_CLIENT_MESSAGE(GattXpanClientUdpPortInd);

    GATT_XPAN_CLIENT_INFO("GXPANC: UdpPort ind. handle = 0x%x size = 0x%x\n", xpanClient->srvcElem->service_handle, size);

    message->clntHndl = xpanClient->srvcElem->service_handle;

    xpanClientDecodeUdpPort(&message->udpPort, size, indData);

    XpanClientMessageSend(xpanClient->app_task, GATT_XPAN_CLIENT_UDP_PORT_IND, message);
}

/****************************************************************************/
static void makeXpanClientRoamingRequestResponseIndMsg(GXPANC *xpanClient, uint16 size, CsrUint8* indData)
{
    MAKE_XPAN_CLIENT_MESSAGE(GattXpanClientRoamingRequestResponseInd);

    GATT_XPAN_CLIENT_INFO("GXPANC: Roaming Request Response ind. handle = 0x%x size = 0x%x\n", xpanClient->srvcElem->service_handle, size);

    message->clntHndl = xpanClient->srvcElem->service_handle;

    xpanClientRoamingRequestResponse(&message->status, size, indData);

    XpanClientMessageSend(xpanClient->app_task, GATT_XPAN_CLIENT_ROAMING_REQUEST_RESPONSE_IND, message);
}

/****************************************************************************
 * This characteristic is read only (it doesn't  Notify)
 ****************************************************************************
static void makeXpanClientMDnsSrvUuidIndMsg(GXPANC *xpanClient, uint16 size, CsrUint8* indData)
{
    MAKE_XPAN_CLIENT_MESSAGE(GattXpanClientMDnsSrvUuidInd);

    GATT_XPAN_CLIENT_INFO("GXPANC: MDnsSrvUuid ind. handle = 0x%x size = 0x%x\n", xpanClient->srvcElem->service_handle, size);

    message->clntHndl = xpanClient->srvcElem->service_handle;

    xpanClientDecodeMDnsSrvUuid(&message->mDnsSrvUuid, size, indData);

    XpanClientMessageSend(xpanClient->app_task, GATT_XPAN_CLIENT_MDNS_SRV_UUID_IND, message);
}
*/
/****************************************************************************/
static void makeXpanClientTwtConfigurationIndMsg(GXPANC *xpanClient, uint16 size, CsrUint8* indData)
{
    MAKE_XPAN_CLIENT_MESSAGE(GattXpanClientTwtConfigurationInd);

    GATT_XPAN_CLIENT_INFO("GXPANC: TwtConfiguration ind. handle = 0x%x size = 0x%x\n", xpanClient->srvcElem->service_handle, size);

    message->clntHndl = xpanClient->srvcElem->service_handle;

    xpanClientDecodeTwtConfiguration(&message->twtConfiguration, size, indData);

    XpanClientMessageSend(xpanClient->app_task, GATT_XPAN_CLIENT_TWT_CONFIGURATION_IND, message);
}

/****************************************************************************/
static void makeXpanClientConnectedDevicesIndMsg(GXPANC *xpanClient, uint16 size, CsrUint8* indData)
{
    MAKE_XPAN_CLIENT_MESSAGE(GattXpanClientConnectedDevicesInd);

    GATT_XPAN_CLIENT_INFO("GXPANC: ConnectedDevices ind. handle = 0x%x size = 0x%x\n", xpanClient->srvcElem->service_handle, size);

    message->clntHndl = xpanClient->srvcElem->service_handle;

    xpanClientDecodeConnectedDevices(&message->connectedDevices, size, indData);

    XpanClientMessageSend(xpanClient->app_task, GATT_XPAN_CLIENT_CONNECTED_DEVICES_IND, message);
}

/****************************************************************************/
static void makeXpanClientClearToSendIndMsg(GXPANC *xpanClient, uint16 size, CsrUint8* indData)
{
    MAKE_XPAN_CLIENT_MESSAGE(GattXpanClientClearToSendInd);

    GATT_XPAN_CLIENT_INFO("GXPANC: ClearToSend ind. handle = 0x%x size = 0x%x\n", xpanClient->srvcElem->service_handle, size);

    message->clntHndl = xpanClient->srvcElem->service_handle;

    xpanClientDecodeClearToSend(&message->clearToSend, size, indData);

    XpanClientMessageSend(xpanClient->app_task, GATT_XPAN_CLIENT_CLEAR_TO_SEND_IND, message);
}

/****************************************************************************/
static void makeXpanClientBearerPreferenceIndMsg(GXPANC *xpanClient, uint16 size, CsrUint8* indData)
{
    MAKE_XPAN_CLIENT_MESSAGE(GattXpanClientBearerPreferenceInd);

    GATT_XPAN_CLIENT_INFO("GXPANC: BearerPreference ind. handle = 0x%x size = 0x%x\n", xpanClient->srvcElem->service_handle, size);

    message->clntHndl = xpanClient->srvcElem->service_handle;

    xpanClientDecodeBearerPreference(&message->bearerPreference, size, indData);

    XpanClientMessageSend(xpanClient->app_task, GATT_XPAN_CLIENT_BEARER_PREFERENCE_IND, message);
}


static void makeXpanClientMacAddressIndMsg(GXPANC *xpanClient, uint16 size, CsrUint8* indData)
{
    MAKE_XPAN_CLIENT_MESSAGE(GattXpanClientMacAddressInd);

    GATT_XPAN_CLIENT_INFO("GXPANC: MacAddress ind. handle = 0x%x size = 0x%x\n", xpanClient->srvcElem->service_handle, size);

    message->clntHndl = xpanClient->srvcElem->service_handle;

    xpanClientDecodeMacAddresses(&message->macAddresses, size, indData);

    XpanClientMessageSend(xpanClient->app_task, GATT_XPAN_CLIENT_MAC_ADDRESS_IND, message);
}

/****************************************************************************/
static void makeXpanClientRequestedSapPowerStateIndMsg(GXPANC *xpanClient, uint16 size, CsrUint8* indData)
{
    MAKE_XPAN_CLIENT_MESSAGE(GattXpanClientRequestedSapPowerStateInd);

    GATT_XPAN_CLIENT_INFO("GXPANC: RequestedSapPowerState ind. handle = 0x%x size = 0x%x\n", xpanClient->srvcElem->service_handle, size);

    message->clntHndl = xpanClient->srvcElem->service_handle;

    xpanClientDecodeRequestedSapPowerState(&message->sapPowerStateData, size, indData);

    XpanClientMessageSend(xpanClient->app_task, GATT_XPAN_CLIENT_REQUESTED_SAP_POWER_STATE_IND, message);
}

/****************************************************************************/
static void makeXpanClientServerFeaturesIndMsg(GXPANC *xpanClient, uint16 size, CsrUint8* indData)
{
    MAKE_XPAN_CLIENT_MESSAGE(GattXpanClientServerFeaturesInd);

    GATT_XPAN_CLIENT_INFO("GXPANC: ServerFeatures ind. handle = 0x%x size = 0x%x\n", xpanClient->srvcElem->service_handle, size);

    message->clntHndl = xpanClient->srvcElem->service_handle;

    xpanClientDecodeServerFeatures(&message->serverFeatures, size, indData);

    XpanClientMessageSend(xpanClient->app_task, GATT_XPAN_CLIENT_SERVER_FEATURES_IND, message);
}

/****************************************************************************/
static void makeXpanClientAudioBearerSwitchResponseIndMsg(GXPANC *xpanClient, uint16 size, CsrUint8* indData)
{
    MAKE_XPAN_CLIENT_MESSAGE(GattXpanClientAudioBearerSwitchResponseInd);

    GATT_XPAN_CLIENT_INFO("GXPANC: AudioBearerSwitchResponse ind. handle = 0x%x size = 0x%x\n", xpanClient->srvcElem->service_handle, size);

    message->clntHndl = xpanClient->srvcElem->service_handle;

    xpanClientDecodeAudioBearerSwitchResponse(&message->audioBearerSwitchResponse, size, indData);

    XpanClientMessageSend(xpanClient->app_task, GATT_XPAN_CLIENT_AUDIO_BEARER_SWITCH_RESPONSE_IND, message);
}

/****************************************************************************/
static void makeXpanClientNumDevicePresentIndMsg(GXPANC *xpanClient, uint16 size, CsrUint8* indData)
{
    MAKE_XPAN_CLIENT_MESSAGE(GattXpanClientNumDevicesPresentInd);

    GATT_XPAN_CLIENT_INFO("GXPANC: NumDevicePresent ind. handle = 0x%x size = 0x%x\n", xpanClient->srvcElem->service_handle, size);

    message->clntHndl = xpanClient->srvcElem->service_handle;

    xpanClientDecodeNumDevicesPresent(&message->numDevices, size, indData);

    XpanClientMessageSend(xpanClient->app_task, GATT_XPAN_CLIENT_NUM_DEVICES_PRESENT_IND, message);
}

/****************************************************************************/
static void makeXpanClientVoiceBackChannelPeriodicityIndMsg(GXPANC *xpanClient, uint16 size, CsrUint8* indData)
{
    MAKE_XPAN_CLIENT_MESSAGE(GattXpanClientVoiceBackChannelPeriodicityInd);

    GATT_XPAN_CLIENT_INFO("GXPANC: VoiceBackChannelPeriodicity ind. handle = 0x%x size = 0x%x\n", xpanClient->srvcElem->service_handle, size);

    message->clntHndl = xpanClient->srvcElem->service_handle;

    xpanClientDecodeVoiceBackChannelPeriodicity(&message->periodicity, size, indData);

    XpanClientMessageSend(xpanClient->app_task, GATT_XPAN_CLIENT_VOICE_BACK_CHANNEL_PERIODICITY_IND, message);
}

/****************************************************************************/
static void makeXpanClientRequestWiFiScanResultsIndMsg(GXPANC *xpanClient, uint16 size, CsrUint8* indData)
{
    MAKE_XPAN_CLIENT_MESSAGE(GattXpanClientRequestWiFiScanResultsInd);

    UNUSED(size);
    UNUSED(indData);

    GATT_XPAN_CLIENT_INFO("GXPANC: XpanClientRequestWiFiScanResults ind. handle = 0x%x size = 0x%x\n", xpanClient->srvcElem->service_handle, size);

    message->clntHndl = xpanClient->srvcElem->service_handle;

    /* There is nothing to decode - the request is empty
     * xpanClientDecodeRequestWiFiScanResults(&message->requestWiFiScanResults, size, indData);
    */
    XpanClientMessageSend(xpanClient->app_task, GATT_XPAN_CLIENT_REQUEST_WIFI_SCAN_RESULTS_IND, message);
}


/****************************************************************************/
void xpanClientHandleClientNotification(GXPANC *xpanClient,
                                        const CsrBtGattClientNotificationInd *ind)
{
    /* Check parameters */
    if (xpanClient == NULL || ind == NULL)
    {
        GATT_XPAN_CLIENT_ERROR("GXPANC: Invalid parameters - xpanClientHandleClientNotification\n");
        return;
    }

    /* QBCESPEC Part G Section 1.5: We need to read the characteristic if there is a possibility
     * that the Notification has been truncated */
    if (ind->valueLength >= (XPAN_CLIENT_GATT_MTU - 3))
    {
        MAKE_XPAN_CLIENT_INTERNAL_MESSAGE(XPAN_CLIENT_INTERNAL_MSG_NOTIFY_READ);

        message->serviceHandle = xpanClient->srvcElem->service_handle;
        message->handle = ind->valueHandle;

        XpanClientMessageSend(xpanClientMain->lib_task,
                              XPAN_CLIENT_INTERNAL_MSG_NOTIFY_READ,
                              message);
    }
    else if (ind->valueLength > 0 && ind->value)
    {
        /* Check the handle if it's a known and send Indication messages to the registered task if a
         *  value has been sent in the notification message */
        if(ind->valueHandle == xpanClient->handles.storedSsidHandle)
        {
            makeXpanClientStoredSsidIndMsg(xpanClient, ind->valueLength, ind->value);
        }
        else if(ind->valueHandle == xpanClient->handles.Ipv4AddressHandle)
        {
            makeXpanClientIpv4AddressIndMsg(xpanClient, ind->valueLength, ind->value);
        }
        else if(ind->valueHandle == xpanClient->handles.Ipv6AddressHandle)
        {
            makeXpanClientIpv6AddressIndMsg(xpanClient, ind->valueLength, ind->value);
        }
        else if(ind->valueHandle == xpanClient->handles.L2capTcpPortHandle)
        {
            makeXpanClientL2capTcpPortIndMsg(xpanClient, ind->valueLength, ind->value);
        }
        else if(ind->valueHandle == xpanClient->handles.UdpPortHandle)
        {
            makeXpanClientUdpPortIndMsg(xpanClient, ind->valueLength, ind->value);
        }
    /* This characteristic doesn't notify
        else if(ind->valueHandle == xpanClient->handles.MDnsSrvUuidHandle)
        {
            makeXpanClientMDnsSrvUuidIndMsg(xpanClient, ind->valueLength, ind->value);
        }
    */
        else if(ind->valueHandle == xpanClient->handles.TwtConfigurationHandle)
        {
            makeXpanClientTwtConfigurationIndMsg(xpanClient, ind->valueLength, ind->value);
        }
        else if(ind->valueHandle == xpanClient->handles.ConnectedDevicesHandle)
        {
            makeXpanClientConnectedDevicesIndMsg(xpanClient, ind->valueLength, ind->value);
        }
        else if(ind->valueHandle == xpanClient->handles.ClearToSendHandle)
        {
            makeXpanClientClearToSendIndMsg(xpanClient, ind->valueLength, ind->value);
        }
        else if(ind->valueHandle == xpanClient->handles.BearerPreferenceHandle)
        {
            makeXpanClientBearerPreferenceIndMsg(xpanClient, ind->valueLength, ind->value);
        }
        else if(ind->valueHandle == xpanClient->handles.MacAddressHandle)
        {
            makeXpanClientMacAddressIndMsg(xpanClient, ind->valueLength, ind->value);
        }
        else if(ind->valueHandle == xpanClient->handles.RequestedSapPowerStateHandle)
        {
            makeXpanClientRequestedSapPowerStateIndMsg(xpanClient, ind->valueLength, ind->value);
        }
        else if (ind->valueHandle == xpanClient->handles.serverFeaturesHandle)
        {
            makeXpanClientServerFeaturesIndMsg(xpanClient, ind->valueLength, ind->value);
        }
        else if (ind->valueHandle == xpanClient->handles.audioBearerSwitchResponseHandle)
        {
            makeXpanClientAudioBearerSwitchResponseIndMsg(xpanClient, ind->valueLength, ind->value);
        }
        else if (ind->valueHandle == xpanClient->handles.numDevicesPresentHandle)
        {
            makeXpanClientNumDevicePresentIndMsg(xpanClient, ind->valueLength, ind->value);
        }
        else if (ind->valueHandle == xpanClient->handles.voiceBackChannelPeriodicityHandle)
        {
            makeXpanClientVoiceBackChannelPeriodicityIndMsg(xpanClient, ind->valueLength, ind->value);
        }
        else if (ind->valueHandle == xpanClient->handles.requestWiFiScanResultsHandle)
        {
            GATT_XPAN_CLIENT_WARNING("GXPANC: RequestWiFiScanResultsInd Notification should be empty (but is not)\n");
            makeXpanClientRequestWiFiScanResultsIndMsg(xpanClient, ind->valueLength, ind->value);
        }
        else if (ind->valueHandle == xpanClient->handles.roamingRequestResponseHandle)
        {
            makeXpanClientRoamingRequestResponseIndMsg(xpanClient, ind->valueLength, ind->value);
        }
        else
        {
            GATT_XPAN_CLIENT_ERROR("GXPANC: Unrecognised handle in Notification 0x%08x\n", ind->valueHandle);
        }
    }
    else
    {
        if (ind->valueHandle == xpanClient->handles.requestWiFiScanResultsHandle)
        {
            makeXpanClientRequestWiFiScanResultsIndMsg(xpanClient, ind->valueLength, ind->value);
        }
    }
}

#endif /* EXCLUDE_GATT_XPAN_CLIENT_MODULE */